package com.zyq.security.aspect;

import com.zyq.security.annotation.RequiresPermissions;
import com.zyq.security.exception.PermissionException;
import com.zyq.security.utils.WebUtils;
import com.zyq.common.util.JWTUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

// 交由spring容器进行管理和创建
@Component
// 标明该类是是一个切面类
@Aspect
public class PreAuthorizeAspect {
    // 注明一个切入点
    // 只要方法上表明该注解都会被切一刀
    @Pointcut(value = "@annotation(com.zyq.security.annotation.RequiresPermissions)")
    public void pointCut(){}

    // 然后再给对应的切入点，附加环绕通知
    @Around(value = "pointCut()")
    public Object around(ProceedingJoinPoint joinPoint){
        System.out.println("hhhhhg");
        // 1. 获取到当前被标记的方法
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        // Result com.zyq.system.controller.AclUserController.list()
        //System.out.println(methodSignature);

        Method method = methodSignature.getMethod();
        // method = public com.zyq.vo.Result com.zyq.system.controller.AclUserController.list()
        //System.out.println("method = " + method);
        // 2. 获取到方法注解里面的值
        // 3. 从请求里面获取到token，拿注解里面的值和token里面的权限进行比较，看是否存在
        checkAnnotation(method);

        // 4. aop是一个动态代理类，需要去回调函数，并返回值
        Object proceed = null;
        try {
            proceed = joinPoint.proceed();
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }

        return proceed;
    }

    private void checkAnnotation(Method method){
        // 1. 获取到方法上的注解对象
        RequiresPermissions annotation = method.getAnnotation(RequiresPermissions.class);
        if(annotation != null){
            // 2. 拿到注解里面的值
            String value = annotation.value();
            // 3. 去请求里面拿到token，创建一个获取到请求的工具类
            HttpServletRequest request = WebUtils.getRequest();
            String token = request.getHeader("token");
            // 4. 校验token，并获取值
            Map<String, Object> tokenChaim = JWTUtil.getTokenChaim(token);
            List<String> permission = (List<String>) tokenChaim.get("permission");
            System.out.println("permission = " + permission);
            System.out.println("value = " + value);
            if(!permission.contains(value)){
                System.out.println("-----权限不足------");
                throw new PermissionException("权限不足啊，请联系管理员");
            }
        }
    }

}
